package com.crowntit.controller;

import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.crowntit.common.Constants;
import com.crowntit.controller.dto.CreateOrderDTO;
import com.crowntit.domain.req.ShopCartReq;
import com.crowntit.domain.res.PayOrderRes;
import com.crowntit.model.Response;
import com.crowntit.service.IOrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@RestController()
@CrossOrigin("*")
@RequestMapping("/api/v1/alipay/")
public class AliPayController {

    @Value("${alipay.alipay_public_key}")
    private String alipayPublicKey;

    @Resource
    private IOrderService orderService;

    @RequestMapping(value = "create_pay_order", method = RequestMethod.POST)
    public Response<String> createOrder(@RequestBody CreateOrderDTO createOrderDTO) {
        try {
            log.info("商品下单，根据商品ID创建支付单开始 userId:{} productId:{}", createOrderDTO.getUserId(), createOrderDTO.getUserId());
            String userId = createOrderDTO.getUserId();
            String productId = createOrderDTO.getProductId();

            ShopCartReq shopCartReq = ShopCartReq.builder()
                    .productId(productId)
                    .userId(userId)
                    .build();
            PayOrderRes payOrder = orderService.createOrder(shopCartReq);
            log.info("商品下单，根据商品ID创建支付单完成 userId:{} productId:{} orderId:{}", userId, productId, payOrder.getOrderId());

            return Response.<String>builder()
                    .code(Constants.ResponseCode.SUCCESS.getCode())
                    .message(Constants.ResponseCode.SUCCESS.getInfo())
                    .data(payOrder.getPayUrl())
                    .build();
        } catch (Exception e) {
            log.error("商品下单，根据商品ID创建支付单失败 userId:{} productId:{}", createOrderDTO.getUserId(), createOrderDTO.getUserId(), e);
            return Response.<String>builder()
                    .code(Constants.ResponseCode.ERROR.getCode())
                    .message(Constants.ResponseCode.ERROR.getInfo())
                    .build();
        }
    }

    @RequestMapping(value = "alipay_notify_url", method = RequestMethod.POST)
    public String payNotify(HttpServletRequest request) throws AlipayApiException {
        log.info("支付回调，消息接收 {}", request.getParameter("trade_status"));

        // 如果状态是TRADE_SUCCESS / TRADE_FINISHED 才是支付成功
        if (!request.getParameter("trade_status").equals("TRADE_SUCCESS")){
            return "false";
        }

        // 1. 验签
        Map<String, String> params = new HashMap<>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (String name : requestParams.keySet()){
            params.put(name, request.getParameter(name));
        }

        String tradeNo = params.get("out_trade_no");
        String gmtPayment = params.get("gmt_payment");
        String alipayTradeNo = params.get("trade_no");

        String sign = params.get("sign");
        String content = AlipaySignature.getSignCheckContentV1(params);
        boolean checkSignature = AlipaySignature.rsa256CheckContent(content, sign, alipayPublicKey, "UTF-8");

        if (!checkSignature){
            return "false";
        }

        // 验签通过
        log.info("支付回调，交易名称: {}", params.get("subject"));
        log.info("支付回调，交易状态: {}", params.get("trade_status"));
        log.info("支付回调，支付宝交易凭证号: {}", params.get("trade_no"));
        log.info("支付回调，商户订单号: {}", params.get("out_trade_no"));
        log.info("支付回调，交易金额: {}", params.get("total_amount"));
        log.info("支付回调，买家在支付宝唯一id: {}", params.get("buyer_id"));
        log.info("支付回调，买家付款时间: {}", params.get("gmt_payment"));
        log.info("支付回调，买家付款金额: {}", params.get("buyer_pay_amount"));
        log.info("支付回调，支付回调，更新订单 {}", tradeNo);

        // 2. 更新订单状态
        orderService.changeOrderPaySuccess(tradeNo);
        return "success";
    }
}
